/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package linkeddata.arida.ufc.br.search;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import linkeddata.arida.ufc.br.manager.impl.BuildsHierarchyDataProperty;
import linkeddata.arida.ufc.br.util.OWLUtils;
import linkeddata.arida.ufc.br.util.TripleStore;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.util.DefaultPrefixManager;

/**
 *
 * @author jeovane
 */
public class HierarchyOfClasses extends OWLUtils {
    
    private OWLOntology ontology;
    private DefaultPrefixManager pm;
    private BuildsHierarchyDataProperty bhdp;

    public HierarchyOfClasses(OWLOntology ontology, OWLReasoner reasoner, DefaultPrefixManager pm) {
        this.ontology = ontology;
        this.pm = pm;
        this.bhdp = new BuildsHierarchyDataProperty(ontology, reasoner, pm);
    }
    
    public Set<String> CorrectHierarchyOfClasses() {
        TripleStore triple;
        Graph graph = new Graph();
        Set<Object> keys = bhdp.buildsHierarchy().keySet();
        ArrayList<String> domainsRanges = new ArrayList<String>();
        ArrayList<String> ranges = new ArrayList<String>();
        Set<String> setNodes = new LinkedHashSet<String>();
        
        for (Iterator it = bhdp.buildsObjectProperty().iterator(); it.hasNext();) {
            triple = (TripleStore) it.next();
            domainsRanges.add(triple.getDomain() + "," + triple.getRange());
            ranges.add(triple.getRange());
        }

        // Adiciona as classes aos nós à arvore [As classes da ontologia]
        for (Object o : keys) {
            String key = pm.getShortForm((OWLEntity) o).replace(":", "");
            Node node = new Node(key);
            graph.setNodes(node);
        }

        // Adiciona os domínios e ranges da Ontologia correspondente ao nós da árvore
        for (int i = 0; i < graph.getNodes().size(); i++) {
            Node nodei = (Node) graph.getNodes().get(i);
            for (int j = 0; j < graph.getNodes().size(); j++) {
                Node nodej = (Node) graph.getNodes().get(j);
                if (domainsRanges.contains(nodei.label + "," + nodej.label)) {
                    graph.connectNode(nodei, nodej);
                }
            }
        }

        // Adiciona o nó pai ao Graph
        for (int i = 0; i < graph.getNodes().size(); i++) {
            Node node = (Node) graph.getNodes().get(i);
            if (node.label.contains(parentNode(domainsRanges, ranges))) {
                graph.setRootNode(node);
            }
        }
        
        for (Node nodes : graph.bfs()){
            setNodes.add(nodes.label);
        }
        
        return setNodes;
    }

    // Procura pelo nó pai
    private String parentNode(ArrayList<String> domainsRanges, ArrayList<String> ranges) {
        String domain = "";
        for (int i = 0; i < domainsRanges.size(); i++) {
            String[] domains = domainsRanges.get(i).split(",");
            for (int j = 0; j < domainsRanges.size(); j++) {
                String[] range = domainsRanges.get(j).split(",");
                if (domains[0].equals(range[1]) || !ranges.contains(domains[0])) {
                    domain = range[0];
                }
            }
        }
        return domain;
    }
}
